<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js"><span id='global-property-'>/**
</span> * @ignore
 * render process for control and render
 * @author yiminghe@gmail.com
 */
KISSY.add('component/control/process', function (S, Base, Promise) {
    var Defer = Promise.Defer,
        __getHook = Base.prototype.__getHook,
        noop = S.noop;

<span id='KISSY-Component-Process'>    /**
</span>     * @class KISSY.Component.Process
     * @extends KISSY.Base
     */
    var ComponentProcess = Base.extend({
        bindInternal: noop,

        syncInternal: noop,

        initializer: function () {
            this._renderedDefer = new Defer();
        },

        createDom: noop,

        renderUI: noop,

        bindUI: noop,

        syncUI: noop,

        onRendered: function (fn) {
            return this._renderedDefer.promise.then(fn);
        },

<span id='KISSY-Component-Process-method-create'>        /**
</span>         * create dom structure of this component
         * (control will delegate to render).
         * @chainable
         */
        create: function () {
            var self = this;
            if (!self.get(&quot;created&quot;)) {
<span id='KISSY-Component-Process-event-beforeCreateDom'>                /**
</span>                 * @event beforeCreateDom
                 * fired before root node is created
                 * @param {KISSY.Event.CustomEvent.Object} e
                 */
                self.fire('beforeCreateDom');
                self.createInternal();
                self.__callPluginsMethod('pluginCreateDom');
<span id='KISSY-Component-Process-event-afterCreateDom'>                /**
</span>                 * @event afterCreateDom
                 * fired when root node is created
                 * @param {KISSY.Event.CustomEvent.Object} e
                 */
                self.fire('afterCreateDom');

                self.setInternal(&quot;created&quot;, true);
            }
            return self;
        },

        createInternal: function () {
            this.createDom();
        },

<span id='KISSY-Component-Process-method-render'>        /**
</span>         * Put dom structure of this component to document, bind event and sync attribute.
         * @chainable
         */
        render: function () {
            var self = this;
            // 是否已经渲染过
            if (!self.get(&quot;rendered&quot;)) {
                self.create();

<span id='KISSY-Component-Process-event-beforeRenderUI'>                /**
</span>                 * @event beforeRenderUI
                 * fired when root node is ready
                 * @param {KISSY.Event.CustomEvent.Object} e
                 */

                self.fire('beforeRenderUI');
                self.renderUI();
                self.__callPluginsMethod('pluginRenderUI');

<span id='KISSY-Component-Process-event-afterRenderUI'>                /**
</span>                 * @event afterRenderUI
                 * fired after root node is rendered into dom
                 * @param {KISSY.Event.CustomEvent.Object} e
                 */
                self.fire('afterRenderUI');

<span id='KISSY-Component-Process-event-beforeBindUI'>                /**
</span>                 * @event beforeBindUI
                 * fired before component 's internal event is bind.
                 * @param {KISSY.Event.CustomEvent.Object} e
                 */

                self.fire('beforeBindUI');
                ComponentProcess.superclass.bindInternal.call(self);
                self.bindUI();
                self.__callPluginsMethod('pluginBindUI');
<span id='KISSY-Component-Process-event-afterBindUI'>                /**
</span>                 * @event afterBindUI
                 * fired when component 's internal event is bind.
                 * @param {KISSY.Event.CustomEvent.Object} e
                 */
                self.fire('afterBindUI');

                ComponentProcess.superclass.syncInternal.call(self);
                syncUIs(self);

                self.setInternal(&quot;rendered&quot;, true);
            }
            return self;
        },

<span id='KISSY-Component-Process-method-sync'>        /**
</span>         * sync attribute value
         */
        sync: function () {
            syncUIs(this);
        },

        plug: function (plugin) {
            var self = this,
                p,
                plugins = self.get('plugins');
            self.callSuper(plugin);
            p = plugins[plugins.length - 1];
            if (self.get('rendered')) {
                // plugin does not support decorate
                p['pluginCreateDom'] &amp;&amp; p['pluginCreateDom'](self);
                p.pluginRenderUI &amp;&amp; p.pluginRenderUI(self);
                p.pluginBindUI &amp;&amp; p.pluginBindUI(self);
                p.pluginSyncUI &amp;&amp; p.pluginSyncUI(self);
            } else if (self.get('created')) {
                p['pluginCreateDom'] &amp;&amp; p['pluginCreateDom'](self);
            }
            return self;
        }

    }, {
        __hooks__: {
            createDom: __getHook('__createDom'),
            renderUI: __getHook('__renderUI'),
            bindUI: __getHook('__bindUI'),
            syncUI: __getHook('__syncUI')
        },

        name: 'ComponentProcess',

        ATTRS: {
<span id='KISSY-Component-Process-property-rendered'>            /**
</span>             * Whether this component is rendered.
             * @type {Boolean}
             * @property rendered
             * @readonly
             */
<span id='global-property-rendered'>            /**
</span>             * @ignore
             */
            rendered: {
                value: false,
                setter: function (v) {
                    if (v) {
                        this._renderedDefer.resolve(this);
                    }
                }
            },
<span id='KISSY-Component-Process-property-created'>            /**
</span>             * Whether this component 's dom structure is created.
             * @type {Boolean}
             * @property created
             * @readonly
             */
<span id='global-property-created'>            /**
</span>             * @ignore
             */
            created: {
                value: false
            }
        }
    });

    function syncUIs(self) {
<span id='KISSY-Component-Process-event-beforeSyncUI'>        /**
</span>         * @event beforeSyncUI
         * fired before component 's internal state is synchronized.
         * @param {KISSY.Event.CustomEvent.Object} e
         */
        self.fire('beforeSyncUI');
        self.syncUI();
        self.__callPluginsMethod('pluginSyncUI');
<span id='KISSY-Component-Process-event-afterSyncUI'>        /**
</span>         * @event afterSyncUI
         * fired after component 's internal state is synchronized.
         * @param {KISSY.Event.CustomEvent.Object} e
         */
        self.fire('afterSyncUI');
    }

    return ComponentProcess;
}, {
    requires: ['base', 'promise']
});
<span id='global-property-'>/**
</span> * @ignore
 *
 * 2013.06.18 note:
 *  - ComponentProcess 流程化渲染过程定义
 *
 * Refer:
 *  - http://martinfowler.com/eaaDev/uiArchs.html
 *
 * render 和 create 区别
 *  - render 包括 create ，以及把生成的节点放在 document 中
 *  - create 仅仅包括创建节点
 **/</pre>
</body>
</html>
